<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>百度语音合成20190313</title>
  <style>
	input,button{font-size:16px;height:34px;box-sizing:border-box;padding:4px 12px;}
	input{padding:4px 8px;}
  </style>
  <script>
	    /**
		 * 浏览器调用语音合成接口
		 * @param {Object} param 百度语音合成接口参数
		 * 请参考 https://ai.baidu.com/docs#/TTS-API/41ac79a6
		 * @param {Object} options 跨域调用api参数
		 *           timeout {number} 超时时间 默认不设置为60秒
		 *           volume {number} audio控件音量，范围 0-1
		 *           hidden {boolean} 是否隐藏audio控件
		 *           autoDestory {boolean} 播放音频完毕后是否自动删除控件
		 *           onInit {Function} 创建完audio控件后调用
		 *           onSuccess {Function} 远程语音合成完成，并且返回音频文件后调用
		 *           onError {Function}  远程语音合成完成，并且返回错误字符串后调用
		 *           onTimeout {Function} 超时后调用，默认超时时间为60秒
		 */
		function btts(param, options) {
		    var url = 'https://tsn.baidu.com/text2audio';
		    var opt = options || {};
		    var p = param || {};
		
		    // 如果浏览器支持，可以设置autoplay，但是不能兼容所有浏览器
		    var audio = document.createElement('audio');
		    if (opt.autoplay) {
		        audio.setAttribute('autoplay', 'autoplay');
		    }
		
		    // 隐藏控制栏
		    if (!opt.hidden) {
		        audio.setAttribute('controls', 'controls');
		    } else {
		        audio.style.display = 'none';
		    }
		
		    // 设置音量
		    if (typeof opt.volume !== 'undefined') {
		        audio.volume = opt.volume;
		    }
		
		    // 调用onInit回调
		    isFunction(opt.onInit) && opt.onInit(audio);
		
		    // 默认超时时间60秒
		    var DEFAULT_TIMEOUT = 60000;
		    var timeout = opt.timeout || DEFAULT_TIMEOUT;
		
		    // 创建XMLHttpRequest对象
		    var xhr = new XMLHttpRequest();
		    xhr.open('POST', url);
		
		    // 创建form参数
		    var data = {};
		    for (var p in param) {
		        data[p] = param[p]
		    }
		
		    // 赋值预定义参数
		    data.cuid = data.cuid || data.tok;
		    data.ctp = 1;
		    data.lan = data.lan || 'zh';
		
		    // 序列化参数列表
		    var fd = [];
		    for(var k in data) {
		        fd.push(k + '=' + encodeURIComponent(data[k]));
		    }
		
		    // 用来处理blob数据
		    var frd = new FileReader();
		    xhr.responseType = 'blob';
		    xhr.send(fd.join('&'));
		
		    // 用timeout可以更兼容的处理兼容超时
		    var timer = setTimeout(function(){
		        xhr.abort();
		        isFunction(opt.onTimeout) && opt.onTimeout();
		    }, timeout);
		
		    xhr.onreadystatechange = function() {
		        if (xhr.readyState == 4) {
		            clearTimeout(timer);
		            if (xhr.status == 200) {
		                if (xhr.response.type === 'audio/mp3') {
		
		                    // 在body元素下apppend音频控件
		                    document.body.append(audio);
		
		                    audio.setAttribute('src', URL.createObjectURL(xhr.response));
		
		                    // autoDestory设置则播放完后移除audio的dom对象
		                    if (opt.autoDestory) {
		                        audio.onended = function() {
		                            document.body.removeChild(audio);
		                        }
		                    }
		
		                    isFunction(opt.onSuccess) && opt.onSuccess(audio);
		                }
		
		                // 用来处理错误
		                if (xhr.response.type === 'application/json') {
		                    frd.onload = function(){
		                        var text = frd.result;
		                        isFunction(opt.onError) && opt.onError(text);
		                    };
		                    frd.readAsText(xhr.response);
		                }
		            }
		        }
		    }
		
		    // 判断是否是函数
		    function isFunction(obj) {
		        if (Object.prototype.toString.call(obj) === '[object Function]') {
		            return true;
		        }
		        return false;
		    }
		}
	  </script>
	  <script type="text/javascript">
	
	    // 初始化变量
	    var audio = null;
	    var playBtn = null;
	
	    // dom加载完毕回调后注册按钮对象
	    ready(function() {
	        playBtn = document.getElementById('playBtn');
	    });
		// 地址栏获取token  https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=Ljl1v49gKua5Du2on5OKfW0X&client_secret=qUgsOhZ2eeIFDiHwvOvWxAzcVKwjyzLL
		
	    // 合成按钮
	    function tts() {
	        let text = document.getElementById('text').value;
	        playBtn.innerText = '准备中';
	
	        // 调用语音合成接口
	        // 参数含义请参考 https://ai.baidu.com/docs#/TTS-API/41ac79a6
	        audio = btts({
	            tex: text,
	            tok: '24.b8f582361fa0f092b4041f2e7f45cb25.2592000.1555035495.282335-14517825',
	            spd: 4,
	            pit: 5,
	            vol: 15,
	            per: 0
	        }, {
	            volume: 1,
	            autoDestory: true,
	            timeout: 10000,
	            hidden: true,
	            onInit: function (htmlAudioElement) {
	
	            },
	            onSuccess: function(htmlAudioElement) {
	                audio = htmlAudioElement;
	                audio.play();
	                playBtn.innerText = '播放';
	            },
	            onError: function(text) {
	                alert(text)
	            },
	            onTimeout: function () {
	                alert('timeout')
	            }
	        });
	    }
	
	    // 播放按钮
	    function play() {
	        if (audio === null) {
	            alert('请先点击合成')
	        } else {
	            audio.play();
	        }
	    }
	
	    // 暂停按钮
	    function pause() {
	        if (audio === null) {
	            alert('请先点击合成')
	        } else {
	            audio.pause();
	        }
	    }
	
	    // 取消按钮
	    function cancel() {
	        if (audio === null) {
	            alert('请先点击合成')
	        } else {
	            audio.pause();
	            document.body.removeChild(audio);
	            audio = null;
	            playBtn.innerText = '准备中';
	        }
	    }
	
	    // dom加载完毕回调
	    function ready(callback){
	        var doc = document;
	        if (doc.addEventListener) {
	            doc.addEventListener('DOMContentLoaded', function() {
	                callback();
	            }, false);
	        } else if (doc.attachEvent) {
	            doc.attachEvent('onreadystatechange', function() {
	                if (doc.readyState === 'complete') {
	                    callback();
	                }
	            });
	        }
	    }
  </script>
</head>
<body>
    <div>
        <input type="text" id='text' value='李心帅，请到诊室就诊，机号 30。' style='width: 300px;'>
        <button onclick='tts()'>合成</button>
        <button onclick='play()' id='playBtn'>准备中</button>
        <button onclick='pause()'>暂停</button>
        <button onclick='cancel()'>取消</button>
    </div>
    <div>
	       本地文件：<audio controls="controls" autoplay="autoplay">
		  <source src="./houlai.mp3" type="audio/mpeg" />
			Your browser does not support the audio element.
		</audio><br>
		 本地文件：<audio controls="controls" src="./houlai.mp3" type="audio/mp3"></audio><br>
		 百度在线source+http：<audio controls="controls" ><br>
			<source src="http://tts.baidu.com/text2audio?lan=zh&amp;ie=UTF-8&amp;spd=2&amp;text=你要转换的文字" type="audio/mpeg" />
		</audio><br>
		 百度在线：<audio controls="controls" src="https://tts.baidu.com/text2audio?lan=zh&amp;ie=UTF-8&amp;spd=2&amp;text=你要转换的文字" type="audio/mp3"></audio>
		 
		 <br>百度在线source+embed+https：<audio controls="controls">
			<source src="https://tts.baidu.com/text2audio?lan=zh&amp;ie=UTF-8&amp;spd=2&amp;text=%E6%B5%8B%E8%AF%95%E7%99%BE%E5%BA%A6%E6%96%87%E5%AD%97%E8%BD%AC%E8%AF%AD%E9%9F%B3%E6%8E%A5%E5%8F%A3%20-%20%E5%8D%A1%E5%8D%A1%E6%B5%8B%E9%80%9F%E7%BD%91%20www.webkaka.com" type="audio/mpeg">
			<embed height="0" width="0" src="https://tts.baidu.com/text2audio?lan=zh&amp;ie=UTF-8&amp;spd=2&amp;text=%E6%B5%8B%E8%AF%95%E7%99%BE%E5%BA%A6%E6%96%87%E5%AD%97%E8%BD%AC%E8%AF%AD%E9%9F%B3%E6%8E%A5%E5%8F%A3%20-%20%E5%8D%A1%E5%8D%A1%E6%B5%8B%E9%80%9F%E7%BD%91%20www.webkaka.com">
		</audio><br>
		5nd.com网络音乐http：<audio controls="controls" src="http://mpge.5nd.com/2019/2019-3-25/90785/1.mp3">
			Your browser does not support the audio element.
		</audio><br>
		develop.yunjingzhi音乐+https：<audio controls="controls" src="https://develop.yunjingzhi.com/yunedu/tpls/houlai.mp3"><p>Oops, looks like your browser doesn't support HTML 5 audio.</p></audio>
		develop.yunjingzhi音乐+http：<audio controls="controls" src="http://develop.yunjingzhi.com/yunedu/tpls/houlai.mp3"><p>Oops, looks like your browser doesn't support HTML 5 audio.</p></audio>
	</div>
	<div id="bdtts_div_id">
        <audio id="tts_autio_id" autoplay="autoplay">
            <source id="tts_source_id" src="https://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&per=0&spd=4&text=" type="audio/mpeg">
            <embed id="tts_embed_id" height="0" width="0" src="">
        </audio>
    </div>
    <script>
    	function doTTS() {
            var ttsDiv = document.getElementById('bdtts_div_id');
            var ttsAudio = document.getElementById('tts_autio_id');
            var ttsText = "输入想播报的文字试试";
            try {
                ttsAudio.pause(); // 
            } catch (e) {}
            // 这样为什么替换不了播放内容
            /*var ssrcc = 'http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=10&text='+ttsText;
            document.getElementById('tts_source_id').src=ssrcc;*/

            // 这样就可实现播放内容的替换了
            ttsDiv.removeChild(ttsAudio);
            var au1 = '<audio id="tts_autio_id" controls="controls" autoplay="autoplay">';
            /* var sss = '<source id="tts_source_id" src="https://tsn.baidu.com/text2audio?tex="'+ttsText+'"&lan=zh&cuid=szjysxxyxgs&ctp=1&tok=24.02a8d9280d8c106cc8accb229cef7bb4.2592000.1542867397.282335-14517825" type="audio/mpeg">'; */
            var sss = '<source id="tts_source_id" src="https://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=3&per=2&text=' +
                ttsText + '" type="audio/mpeg">';
            var eee = '<embed id="tts_embed_id" height="0" width="0" src="">';
            var au2 = '</audio>';
            ttsDiv.innerHTML = au1 + sss + eee + au2;

            ttsAudio = document.getElementById('tts_autio_id');
			try{
				ttsAudio.load();
    			ttsAudio.pause(); 
				setTimeout(function(){
					ttsAudio.play();},300)
			}catch(e){console.log(e)}
            
            
        }
        doTTS()
		if(typeof URL.createObjectURL != 'function'){alert("不支持URL.createObjectURL")}
    </script>
</body>
</html>